package fr.univ.surveyonline.dispatcher;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import fr.univ.surveyonline.datastore.DatastoreKeyResponse;
import fr.univ.surveyonline.datastore.PMF;
import fr.univ.surveyonline.model.Barometre;
import fr.univ.surveyonline.model.DateHelpers;
import fr.univ.surveyonline.model.Response;
import fr.univ.surveyonline.question.FormField;
import fr.univ.surveyonline.question.IChoiceField;
import fr.univ.surveyonline.question.ICompositeField;
import fr.univ.surveyonline.question.IMultipleSuccessorField;
import fr.univ.surveyonline.question.TypeCompositeField;

@SuppressWarnings("serial")
public class SurveyResults extends HttpServlet {
	
	@SuppressWarnings("unchecked")
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException	{
		FormField f = (FormField) req.getSession().getAttribute("formfield");
		if (f == null) {
			throw new IllegalStateException("Pas de FormField en session");
		}
		String id = req.getParameter("id");
		
		ICompositeField cf = getCompositeFieldWithKey(f,id);
		if (cf == null) {
			throw new IllegalStateException("l'id n'appartient pas au questionnaire");
		}
		
		String query = "select from " + Response.class.getName() + " where compositeFieldKey=='" + id + "'";
		List<Response> list = (List<Response>) PMF.executeQuery(query);
		
		Barometre b = (Barometre) req.getSession().getAttribute("barometre");
		
		
		resp.setContentType("text/xml");		
		StringBuffer sb = new StringBuffer(""); 
		sb.append("<results>");
		
		if (b == null) {
			ResponseInformation ri = new ResponseInformation(cf);
			for (Response r : list) {
				ri.addResponse(r);
			}
			
			ri.makeResult(sb);
		} else {
			Date beginDate = (Date) req.getSession().getAttribute("dateBegin");
			Map<Integer,ResponseInformation> map = new TreeMap<Integer,ResponseInformation>();
			for (Response r : list) {
				ResponseInformation ri = map.get(r.getBarometreNummer());
				if (ri == null) {
					ri = new ResponseInformation(cf);
					map.put(r.getBarometreNummer(), ri);
				}
				ri.addResponse(r);
			}
			
			for (int i : map.keySet()) {
				Date d = this.calculDate(i,b.getRepetition_frequence(),beginDate);
				sb.append("<date value=\"" + DateHelpers.dateToString(d) + "\">" );
				map.get(i).makeResult(sb);
				sb.append("</date>");
			}
					
		}

		sb.append("</results>");
		//System.out.println(sb.toString());
		resp.getWriter().print(sb.toString());
	}

	
	private Date calculDate(int i, int repetitionFrequence, Date beginDate) {
		Calendar c = Calendar.getInstance();
		c.setTime(beginDate);
		c.add(Calendar.DAY_OF_MONTH, i * repetitionFrequence);
		
		return c.getTime();
	}
	
	private class ResponseInformation {
		private Set<Long> usersId;
		private Map<String,Integer> map;
		private Map<String,String> toResponse;
		
		private ResponseInformation(ICompositeField cf) {
			map = new HashMap<String,Integer>();
			initResponse(cf);
			usersId = new HashSet<Long>();
		}
		
		private void initResponse(ICompositeField cf) {
			if (cf.getType() == TypeCompositeField.TEXT_FIELD) {
				throw new IllegalStateException("Pas de TextField");
			}
			toResponse = new HashMap<String,String>();
			IChoiceField ch = (IChoiceField) cf; 
			for (DatastoreKeyResponse key : ch.getAllKey()) {
				String response = ch.getAnswer(key);
				toResponse.put(key.toString(), response);
				map.put(response,0);
			}
		}

		private void addResponse(Response r) {
			this.usersId.add(r.getUserKey().getId());
			String response = toResponse.get(r.getResponse()); 
			this.map.put(response, this.map.get(response) +1);
		}
		
		private int getUserNumber() {
			return usersId.size();
		}
		
		private void makeResult(StringBuffer sb) {
			int number = this.getUserNumber();
			
			for (String s : this.map.keySet()) {
				sb.append("<result>");
				sb.append("<response>" + s + "</response>");
				sb.append("<value>" + this.div(map.get(s),number)+ "</value>");
				sb.append("</result>");
			}
		}
		/**
		 * On choppe juste 1 chiffre apres la virgule
		 */
		private String div(int a, int b) {
			if (b < 0) {
				return 0 + "";
			}
			double a1 = (double) a * 100;
			double b1 = (double) b;

			String res = (a1/b1) + "";
			int ind = res.indexOf(".");
			if ((ind > 0) &&(ind < res.length() -1)){
				res = res.substring(0, ind + 1);
			}
			return res;
		}
	}
	
	private ICompositeField getCompositeFieldWithKey(FormField f, String id) {
		Iterator<ICompositeField> it = f.getIterator();
		while (it.hasNext()) {
			ICompositeField cf = it.next();
			if (cf.getKey().toString().equals(id)) {
				return cf;
			}
			
			if (cf.getType() == TypeCompositeField.MULTIPLE_SUCCESSOR_FIELD) {
				IMultipleSuccessorField icf = (IMultipleSuccessorField) cf;
				for (DatastoreKeyResponse k : icf.getAllKey()) {
					FormField fils = icf.getChildren(k);
					if (fils != null) {
						ICompositeField res = getCompositeFieldWithKey(fils, id);
						if (res != null) {
							return res;
						}
					}
				}
			}
		}
		return null;
	}
}
